home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #14 / Monster Media No. 14 (April 1996) (Monster Media, Inc.).ISO / prog_d / isamexpt.zip / ISAMNAV.PAS < prev    next >
Pascal/Delphi Source File  |  1996-01-13  |  14KB  |  525 lines

  1. unit Isamnav;
  2. {copyright 1995 by Norbert Stellberg GmbH}
  3. interface
  4.  
  5. Uses Classes, WinProcs, WinTypes, ExtCtrls, Controls,
  6.      IsamBrow, DbCtrls, Messages, Buttons;
  7.  
  8. Type
  9.   TIsamNavButton = class;
  10.   TIsamNavigateBtn = (nbFirst, nbPrior, nbNext, nbLast,
  11.                       nbInsert, nbDelete);
  12.   TIsamButtonSet = set of TIsamNavigateBtn;
  13.  
  14. { tIsamNavigator }
  15.  
  16.   TIsamNavigator = class (TCustomPanel)
  17.   {NAVIGATOR for isamtables, compatible with NAVIGATORS
  18.    for IDAPI-driven tables.}
  19.   private
  20.     FBrowser: TIsamBrowser;
  21.     FVisibleButtons: TIsamButtonSet;
  22.     FHints: TStrings;
  23.     ButtonWidth: Integer;
  24.     MinBtnSize: TPoint;
  25.     FOnNavClick: ENavClick;
  26.     FocusedButton: TIsamNavigateBtn;
  27.     FConfirmDelete: Boolean;
  28.     procedure SetBrowser(Value: TIsamBrowser);
  29.     procedure InitButtons;
  30.     procedure InitHints;
  31.     procedure Click(Sender: TObject);
  32.     procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
  33.       Shift: TShiftState; X, Y: Integer);
  34.     procedure SetVisible(Value: TIsamButtonSet);
  35.     procedure AdjustSize (var W: Integer; var H: Integer);
  36.     procedure SetHints(Value: TStrings);
  37.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  38.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  39.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  40.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  41.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  42.   protected
  43.     Buttons: array[TIsamNavigateBtn] of tIsamNavButton;
  44.     procedure DataChanged;
  45.     procedure EditingChanged;
  46.     procedure ActiveChanged;
  47.     procedure Loaded; override;
  48.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  49.     procedure Notification(AComponent: TComponent;
  50.       Operation: TOperation); override;
  51.   public
  52.     constructor Create(AOwner: TComponent); override;
  53.     destructor Destroy; override;
  54.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  55.     procedure BtnClick(Index: tIsamNavigateBtn);
  56.   published
  57.     property Browser: TIsamBrowser read FBrowser write SetBrowser;
  58.     property VisibleButtons: TIsamButtonSet read FVisibleButtons write SetVisible
  59.       default [nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete];
  60.     property Align;
  61.     property DragCursor;
  62.     property DragMode;
  63.     property Enabled;
  64.     property Ctl3D;
  65.     property Hints: TStrings read FHints write SetHints;
  66.     property ParentCtl3D;
  67.     property ParentShowHint;
  68.     property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
  69.     property ShowHint;
  70.     property TabOrder;
  71.     property TabStop;
  72.     property Visible;
  73.     property OnClick: ENavClick read FOnNavClick write FOnNavClick;
  74.     property OnDblClick;
  75.     property OnDragDrop;
  76.     property OnDragOver;
  77.     property OnEndDrag;
  78.     property OnEnter;
  79.     property OnExit;
  80.     property OnResize;
  81.   end;
  82.  
  83. { tIsamNavButton }
  84.  
  85.   tIsamNavButton = class(TSpeedButton)
  86.   private
  87.     FIndex: TIsamNavigateBtn;
  88.     FNavStyle: tNavButtonStyle;
  89.     FRepeatTimer: TTimer;
  90.     procedure TimerExpired(Sender: TObject);
  91.   protected
  92.     procedure Paint; override;
  93.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  94.       X, Y: Integer); override;
  95.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  96.       X, Y: Integer); override;
  97.   public
  98.     destructor Destroy; override;
  99.     property NavStyle: tNavButtonStyle read FNavStyle write FNavStyle;
  100.     property Index : TIsamNavigateBtn read FIndex write FIndex;
  101.   end;
  102.  
  103.   procedure Register;
  104.  
  105. implementation
  106.  
  107. Uses DbConsts, SysUtils, Forms, Dialogs;
  108.  
  109. const
  110.   BtnStateName: array[TNavGlyph] of PChar = ('EN', 'DI');
  111.   BtnTypeName: array[TIsamNavigateBtn] of PChar = ('FIRST', 'PRIOR', 'NEXT',
  112.     'LAST', 'INSERT', 'DELETE');
  113.   BtnHintId: array[TIsamNavigateBtn] of Word = (SFirstRecord, SPriorRecord,
  114.     SNextRecord, SLastRecord, SInsertRecord, SDeleteRecord);
  115.  
  116. constructor tIsamNavigator.Create(AOwner: TComponent);
  117. begin
  118.   inherited Create(AOwner);
  119.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] +
  120.     [csFramed, csOpaque];
  121.   FVisibleButtons := [nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete];
  122.   FHints := TStringList.Create;
  123.   InitButtons;
  124.   BevelOuter := bvNone;
  125.   BevelInner := bvNone;
  126.   Width := 241;
  127.   Height := 25;
  128.   ButtonWidth := 0;
  129.   FocusedButton := nbFirst;
  130.   FConfirmDelete := True;
  131. end;
  132.  
  133. destructor tIsamNavigator.Destroy;
  134. begin
  135.   {FDataLink.Free;
  136.   FDataLink := nil;}
  137.   inherited Destroy;
  138. end;
  139.  
  140. procedure tIsamNavigator.InitButtons;
  141. var
  142.   I: TIsamNavigateBtn;
  143.   Btn: tIsamNavButton;
  144.   X: Integer;
  145.   ResName: array[0..40] of Char;
  146. begin
  147.   MinBtnSize := Point(20, 18);
  148.   X := 0;
  149.   for I := Low(Buttons) to High(Buttons) do
  150.   begin
  151.     Btn := tIsamNavButton.Create (Self);
  152.     Btn.Index := I;
  153.     Btn.Visible := I in FVisibleButtons;
  154.     Btn.Enabled := True;
  155.     Btn.SetBounds (X, 0, MinBtnSize.X, MinBtnSize.Y);
  156.     Btn.Glyph.Handle := LoadBitmap(HInstance,
  157.         StrFmt(ResName, 'dbn_%s', [BtnTypeName[I]]));
  158.     Btn.NumGlyphs := 2;
  159.     Btn.OnClick := Click;
  160.     Btn.OnMouseDown := BtnMouseDown;
  161.     Btn.Parent := Self;
  162.     Buttons[I] := Btn;
  163.     X := X + MinBtnSize.X;
  164.   end;
  165.   InitHints;
  166.   Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer];
  167.   Buttons[nbNext].NavStyle  := Buttons[nbNext].NavStyle + [nsAllowTimer];
  168. end;
  169.  
  170. procedure tIsamNavigator.InitHints;
  171. var
  172.   I: Integer;
  173.   J: TIsamNavigateBtn;
  174. begin
  175.   for J := Low(Buttons) to High(Buttons) do
  176.     Buttons[J].Hint := LoadStr (BtnHintId[J]);
  177.   J := Low(Buttons);
  178.   for I := 0 to (FHints.Count - 1) do
  179.   begin
  180.     if FHints.Strings[I] <> '' then Buttons[J].Hint := FHints.Strings[I];
  181.     if J = High(Buttons) then Exit;
  182.     Inc(J);
  183.   end;
  184. end;
  185.  
  186. procedure tIsamNavigator.SetHints(Value: TStrings);
  187. begin
  188.   FHints.Assign(Value);
  189.   InitHints;
  190. end;
  191.  
  192. procedure tIsamNavigator.Notification(AComponent: TComponent;
  193.   Operation: TOperation);
  194. begin
  195.   inherited Notification(AComponent, Operation);
  196.   {if (Operation = opRemove) and (FDataLink <> nil) and
  197.     (AComponent = DataSource) then DataSource := nil;}
  198. end;
  199.  
  200. procedure tIsamNavigator.DataChanged;
  201. begin
  202. end;
  203.  
  204. procedure tIsamNavigator.EditingChanged;
  205. begin
  206. end;
  207.  
  208. procedure tIsamNavigator.SetVisible(Value: TIsamButtonSet);
  209. var
  210.   I: tIsamNavigateBtn;
  211.   W, H: Integer;
  212. begin
  213.   W := Width;
  214.   H := Height;
  215.   FVisibleButtons := Value;
  216.   for I := Low(Buttons) to High(Buttons) do
  217.     Buttons[I].Visible := I in FVisibleButtons;
  218.   AdjustSize (W, H);
  219.   if (W <> Width) or (H <> Height) then
  220.     inherited SetBounds (Left, Top, W, H);
  221.   Invalidate;
  222. end;
  223.  
  224. procedure tIsamNavigator.AdjustSize (var W: Integer; var H: Integer);
  225. var
  226.   Count: Integer;
  227.   MinW: Integer;
  228.   I: tIsamNavigateBtn;
  229.   LastBtn: tIsamNavigateBtn;
  230.   Space, Temp, Remain: Integer;
  231.   X: Integer;
  232. begin
  233.   if (csLoading in ComponentState) then Exit;
  234.   if Buttons[nbFirst] = nil then Exit;
  235.  
  236.   Count := 0;
  237.   LastBtn := High(Buttons);
  238.   for I := Low(Buttons) to High(Buttons) do
  239.   begin
  240.     if Buttons[I].Visible then
  241.     begin
  242.       Inc(Count);
  243.       LastBtn := I;
  244.     end;
  245.   end;
  246.   if Count = 0 then Inc(Count);
  247.  
  248.   MinW := Count * (MinBtnSize.X - 1) + 1;
  249.   if W < MinW then
  250.     W := MinW;
  251.   if H < MinBtnSize.Y then
  252.     H := MinBtnSize.Y;
  253.  
  254.   ButtonWidth := ((W - 1) div Count) + 1;
  255.   Temp := Count * (ButtonWidth - 1) + 1;
  256.   if Align = alNone then
  257.     W := Temp;
  258.  
  259.   X := 0;
  260.   Remain := W - Temp;
  261.   Temp := Count div 2;
  262.   for I := Low(Buttons) to High(Buttons) do
  263.   begin
  264.     if Buttons[I].Visible then
  265.     begin
  266.       Space := 0;
  267.       if Remain <> 0 then
  268.       begin
  269.         Dec (Temp, Remain);
  270.         if Temp < 0 then
  271.         begin
  272.           Inc (Temp, Count);
  273.           Space := 1;
  274.         end;
  275.       end;
  276.       Buttons[I].SetBounds (X, 0, ButtonWidth + Space, Height);
  277.       Inc (X, ButtonWidth - 1 + Space);
  278.       LastBtn := I;
  279.     end
  280.     else
  281.       Buttons[I].SetBounds (Width + 1, 0, ButtonWidth, Height);
  282.   end;
  283. end;
  284.  
  285. procedure tIsamNavigator.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  286. var
  287.   W, H: Integer;
  288. begin
  289.   W := AWidth;
  290.   H := AHeight;
  291.   AdjustSize (W, H);
  292.   inherited SetBounds (ALeft, ATop, W, H);
  293. end;
  294.  
  295. procedure tIsamNavigator.WMSize(var Message: TWMSize);
  296. var
  297.   W, H: Integer;
  298. begin
  299.   inherited;
  300.  
  301.   { check for minimum size }
  302.   W := Width;
  303.   H := Height;
  304.   AdjustSize (W, H);
  305.   if (W <> Width) or (H <> Height) then
  306.     inherited SetBounds(Left, Top, W, H);
  307.   Message.Result := 0;
  308. end;
  309.  
  310. procedure tIsamNavigator.Click(Sender: TObject);
  311. begin
  312.   BtnClick (tIsamNavButton (Sender).Index);
  313. end;
  314.  
  315. procedure tIsamNavigator.BtnMouseDown(Sender: TObject; Button: TMouseButton;
  316.   Shift: TShiftState; X, Y: Integer);
  317. var
  318.   OldFocus: tIsamNavigateBtn;
  319.   Form: TForm;
  320. begin
  321.   OldFocus := FocusedButton;
  322.   FocusedButton := tIsamNavButton (Sender).Index;
  323.   if TabStop and (GetFocus <> Handle) and CanFocus then
  324.   begin
  325.     SetFocus;
  326.     if (GetFocus <> Handle) then
  327.       Exit;
  328.   end
  329.   else if TabStop and (GetFocus = Handle) and (OldFocus <> FocusedButton) then
  330.   begin
  331.     Buttons[OldFocus].Invalidate;
  332.     Buttons[FocusedButton].Invalidate;
  333.   end;
  334. end;
  335.  
  336. procedure tIsamNavigator.BtnClick(Index: tIsamNavigateBtn);
  337. begin
  338.   if Assigned(FBrowser) then begin
  339.     if Browser <> NIL then begin
  340.       if Browser.Table <> NIL then with Browser do begin
  341.         case Index of
  342.           nbPrior: SendMessage(Browser.Handle, WM_KeyDown, vk_UP, 0);
  343.           nbNext : SendMessage(Browser.Handle, WM_KeyDown, vk_Down, 0);
  344.           nbFirst: SetAndupDateBrowserScreen('',0);
  345.           nbLast : SetAndupdateBrowserScreen(#255,9999999);
  346.           nbInsert: SendMessage(Browser.Handle, WM_KeyDown, vk_Insert, 0);
  347.           nbDelete: begin
  348.                       if not FConfirmDelete or (MessageDlg (LoadStr(SDeleteRecordQuestion),
  349.                              mtConfirmation, mbOKCancel, 0) <> idCancel) then
  350.                       SendMessage(Browser.Handle, WM_KeyDown, vk_Delete, 0);
  351.                     end;
  352.         end;
  353.       end;
  354.     end;
  355.   end;
  356.   if not (csDesigning in ComponentState) and Assigned(FOnNavClick) then {FOnNavClick(Self, Index)};
  357. end;
  358.  
  359. procedure tIsamNavigator.WMSetFocus(var Message: TWMSetFocus);
  360. begin
  361.   Buttons[FocusedButton].Invalidate;
  362. end;
  363.  
  364. procedure tIsamNavigator.WMKillFocus(var Message: TWMKillFocus);
  365. begin
  366.   Buttons[FocusedButton].Invalidate;
  367. end;
  368.  
  369. procedure tIsamNavigator.KeyDown(var Key: Word; Shift: TShiftState);
  370. var
  371.   NewFocus: tIsamNavigateBtn;
  372.   OldFocus: tIsamNavigateBtn;
  373. begin
  374.   OldFocus := FocusedButton;
  375.   case Key of
  376.     VK_RIGHT:
  377.       begin
  378.         NewFocus := FocusedButton;
  379.         repeat
  380.           if NewFocus < High(Buttons) then
  381.             NewFocus := Succ(NewFocus);
  382.         until (NewFocus = High(Buttons)) or (Buttons[NewFocus].Visible);
  383.         if NewFocus <> FocusedButton then
  384.         begin
  385.           FocusedButton := NewFocus;
  386.           Buttons[OldFocus].Invalidate;
  387.           Buttons[FocusedButton].Invalidate;
  388.         end;
  389.       end;
  390.     VK_LEFT:
  391.       begin
  392.         NewFocus := FocusedButton;
  393.         repeat
  394.           if NewFocus > Low(Buttons) then
  395.             NewFocus := Pred(NewFocus);
  396.         until (NewFocus = Low(Buttons)) or (Buttons[NewFocus].Visible);
  397.         if NewFocus <> FocusedButton then
  398.         begin
  399.           FocusedButton := NewFocus;
  400.           Buttons[OldFocus].Invalidate;
  401.           Buttons[FocusedButton].Invalidate;
  402.         end;
  403.       end;
  404.     VK_SPACE:
  405.       begin
  406.         if Buttons[FocusedButton].Enabled then
  407.           Buttons[FocusedButton].Click;
  408.       end;
  409.   end;
  410. end;
  411.  
  412. procedure tIsamNavigator.WMGetDlgCode(var Message: TWMGetDlgCode);
  413. begin
  414.   Message.Result := DLGC_WANTARROWS;
  415. end;
  416.  
  417. procedure tIsamNavigator.ActiveChanged;
  418. var
  419.   I: tIsamNavigateBtn;
  420. begin
  421.   if not (Enabled) then
  422.     for I := Low(Buttons) to High(Buttons) do
  423.       Buttons[I].Enabled := False
  424.   else
  425.   begin
  426.     DataChanged;
  427.     EditingChanged;
  428.   end;
  429. end;
  430.                   
  431. procedure tIsamNavigator.CMEnabledChanged(var Message: TMessage);
  432. begin
  433.   inherited;
  434.   if not (csLoading in ComponentState) then
  435.     ActiveChanged;
  436. end;
  437.  
  438. procedure tIsamNavigator.Loaded;
  439. var
  440.   W, H: Integer;
  441. begin
  442.   inherited Loaded;
  443.   W := Width;
  444.   H := Height;
  445.   AdjustSize (W, H);
  446.   if (W <> Width) or (H <> Height) then
  447.     inherited SetBounds (Left, Top, W, H);
  448.   InitHints;
  449.   ActiveChanged;
  450. end;
  451.  
  452. Procedure tIsamNavigator.SetBrowser(Value: TIsamBrowser);
  453. begin
  454.   FBrowser:= Value;
  455. end;
  456.  
  457. {tIsamNavButton}
  458.  
  459. destructor tIsamNavButton.Destroy;
  460. begin
  461.   if FRepeatTimer <> nil then
  462.     FRepeatTimer.Free;
  463.   inherited Destroy;
  464. end;
  465.  
  466. procedure tIsamNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  467.   X, Y: Integer);
  468. begin
  469.   inherited MouseDown (Button, Shift, X, Y);
  470.   if nsAllowTimer in FNavStyle then
  471.   begin
  472.     if FRepeatTimer = nil then
  473.       FRepeatTimer := TTimer.Create(Self);
  474.  
  475.     FRepeatTimer.OnTimer := TimerExpired;
  476.     FRepeatTimer.Interval := InitRepeatPause;
  477.     FRepeatTimer.Enabled  := True;
  478.   end;
  479. end;
  480.  
  481. procedure tIsamNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  482.                                   X, Y: Integer);
  483. begin
  484.   inherited MouseUp (Button, Shift, X, Y);
  485.   if FRepeatTimer <> nil then
  486.     FRepeatTimer.Enabled  := False;
  487. end;
  488.  
  489. procedure tIsamNavButton.TimerExpired(Sender: TObject);
  490. begin
  491.   FRepeatTimer.Interval := RepeatPause;
  492.   if (FState = bsDown) and MouseCapture then
  493.   begin
  494.     try
  495.       Click;
  496.     except
  497.       FRepeatTimer.Enabled := False;
  498.       raise;
  499.     end;
  500.   end;
  501. end;
  502.  
  503. procedure tIsamNavButton.Paint;
  504. var
  505.   R: TRect;
  506. begin
  507.   inherited Paint;
  508.   if (GetFocus = Parent.Handle) and
  509.      (FIndex = TIsamNavigator (Parent).FocusedButton) then
  510.   begin
  511.     R := Bounds(0, 0, Width, Height);
  512.     InflateRect(R, -3, -3);
  513.     if FState = bsDown then
  514.       OffsetRect(R, 1, 1);
  515.     DrawFocusRect(Canvas.Handle, R);
  516.   end;
  517. end;
  518.                 
  519. procedure Register;
  520. begin
  521.   RegisterComponents('B-Tree Filer', [TIsamNavigator]);
  522. end;
  523.  
  524. end.
  525.